#include "../test_helpers.h"
#include "SignatureHelper.h"
#include <spdlog/spdlog.h>
#include <gtest/gtest.h>

using namespace MessageFramework;
using namespace MessageFramework::Test;

class SignatureHelperTest : public ::testing::Test {
protected:
    std::string secretKey = "test-secret-key-32bytes-long!!!";

    void SetUp() override {
        spdlog::set_level(spdlog::level::debug);
    }
};

// ==================== 签名生成测试 ====================

TEST_F(SignatureHelperTest, SignMessage) {
    MessageHeader header = TestHelpers::createTestHeader();
    std::string body = TestHelpers::createTestBody();

    // 签名前signature应该为空
    EXPECT_EQ(std::strlen(header.signature), 0);

    // 生成签名
    std::string signature = SignatureHelper::sign(header, body, secretKey);

    // 验证签名不为空
    EXPECT_GT(signature.length(), 0);
    EXPECT_GT(std::strlen(header.signature), 0);

    // 验证signature字段被填充
    EXPECT_STREQ(header.signature, signature.c_str());
}

TEST_F(SignatureHelperTest, SignatureDeterministic) {
    MessageHeader header = TestHelpers::createTestHeader();
    std::string body = TestHelpers::createTestBody();

    // 相同内容应该生成相同签名
    std::string sig1 = SignatureHelper::sign(header, body, secretKey);

    // 重置signature字段
    header.signature[0] = '\0';

    std::string sig2 = SignatureHelper::sign(header, body, secretKey);

    EXPECT_EQ(sig1, sig2);
}

TEST_F(SignatureHelperTest, DifferentBodyDifferentSignature) {
    MessageHeader header = TestHelpers::createTestHeader();

    std::string sig1 = SignatureHelper::sign(header, "body1", secretKey);
    header.signature[0] = '\0';

    std::string sig2 = SignatureHelper::sign(header, "body2", secretKey);

    EXPECT_NE(sig1, sig2);
}

// ==================== 签名验证测试 ====================

TEST_F(SignatureHelperTest, VerifyValidSignature) {
    MessageHeader header = TestHelpers::createTestHeader();
    std::string body = TestHelpers::createTestBody();

    // 生成签名
    SignatureHelper::sign(header, body, secretKey);

    // 验证签名
    bool valid = SignatureHelper::verify(header, body, secretKey, 0);  // timeWindow=0表示不检查时间
    EXPECT_TRUE(valid);
}

TEST_F(SignatureHelperTest, VerifyInvalidSignature) {
    MessageHeader header = TestHelpers::createTestHeader();
    std::string body = TestHelpers::createTestBody();

    SignatureHelper::sign(header, body, secretKey);

    // 篡改签名
    header.signature[0] = 'X';

    bool valid = SignatureHelper::verify(header, body, secretKey, 0);
    EXPECT_FALSE(valid);
}

TEST_F(SignatureHelperTest, VerifyWrongKey) {
    MessageHeader header = TestHelpers::createTestHeader();
    std::string body = TestHelpers::createTestBody();

    SignatureHelper::sign(header, body, secretKey);

    // 使用错误的密钥验证
    std::string wrongKey = "wrong-secret-key-32bytes-long!!";
    bool valid = SignatureHelper::verify(header, body, wrongKey, 0);

    EXPECT_FALSE(valid);
}

TEST_F(SignatureHelperTest, VerifyTamperedBody) {
    MessageHeader header = TestHelpers::createTestHeader();
    std::string body = "original body";

    SignatureHelper::sign(header, body, secretKey);

    // 验证被篡改的body
    std::string tamperedBody = "tampered body";
    bool valid = SignatureHelper::verify(header, tamperedBody, secretKey, 0);

    EXPECT_FALSE(valid);
}

// ==================== 时间窗口验证测试 ====================

TEST_F(SignatureHelperTest, TimeWindowValid) {
    MessageHeader header = TestHelpers::createTestHeader();
    std::string body = TestHelpers::createTestBody();

    SignatureHelper::sign(header, body, secretKey);

    // 60秒时间窗口内应该有效
    bool valid = SignatureHelper::verify(header, body, secretKey, 60);
    EXPECT_TRUE(valid);
}

TEST_F(SignatureHelperTest, TimeWindowExpired) {
    MessageHeader header = TestHelpers::createTestHeader();

    // 设置为2小时前
    auto past = std::chrono::high_resolution_clock::now() - std::chrono::hours(2);
    header.timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(
        past.time_since_epoch()).count();

    std::string body = TestHelpers::createTestBody();
    SignatureHelper::sign(header, body, secretKey);

    // 60秒时间窗口应该验证失败
    bool valid = SignatureHelper::verify(header, body, secretKey, 60);
    EXPECT_FALSE(valid);
}

// ==================== Body哈希测试 ====================

TEST_F(SignatureHelperTest, HashBody) {
    std::string body1 = "test body";
    std::string body2 = "test body";
    std::string body3 = "different body";

    std::string hash1 = SignatureHelper::hashBody(body1);
    std::string hash2 = SignatureHelper::hashBody(body2);
    std::string hash3 = SignatureHelper::hashBody(body3);

    // 相同内容哈希相同
    EXPECT_EQ(hash1, hash2);

    // 不同内容哈希不同
    EXPECT_NE(hash1, hash3);

    // SHA256哈希长度应该是64个十六进制字符
    EXPECT_EQ(hash1.length(), 64);
}

int main(int argc, char** argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
